`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    19:35:51 07/05/2015 
// Design Name: 
// Module Name:    algorithm 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module algorithm(aclk,vt_ave,ocv);
  input aclk;//algorithm clk,7.5354HZ
  input [13:0] vt_ave;//terminal voltage from adc 0~16383
  output [9:0] ocv;//output 10bit ocv
  
  
  reg state=1'b0;//state
  reg [26:0] vo=27'b0;//open circuit voltage
  reg [26:0] vp=27'b0;//RC voltage
  wire [26:0] it;//load current  
  
  //vt from 0~16383 to 0~5
  wire [26:0] vt;//vt*2^24
  wire [22:0] vt1;
  assign vt1=vt_ave*320;//320 2^20
  assign vt={vt1,4'b0};
  
  //state
  always @(negedge aclk) begin
    if(state==0) state<=1;
  end
 
  //slope
  wire [22:0] slope;//2^20
  assign slope=(vo>=66270003)?37:
               (vo>=61236838 && vo<66270003)?11:173;
  
  //vo,dvo
  wire [26:0] dvo;
  wire [46:0] dvo1;
  assign dvo1=it*slope;
  assign dvo=dvo1[46:20];
  always @(negedge aclk) begin
    if(state==0) vo<=vt;
    else vo<=vo-dvo;
  end
  
  //vp
  wire [46:0] vp1;
  wire [26:0] vp2;
  wire [45:0] dvp1;
  wire [26:0] dvp;
  assign vp1=vp*1046588;//16 2^20
  assign vp2=vp1[46:20];
  assign dvp1=it*144;//144 2^19
  assign dvp=dvp1[45:19];
  always @(negedge aclk) begin
    vp<=vp2+dvp;
  end
  
  //it
  reg [37:0] it1=38'b0;
  always @(negedge aclk)
    if(state==1)
      it1<=(vo-vp-vt)*7642;//7642 2^11
  assign it=it1[37:11];


  //ocv
  wire [34:0] vo1;
  assign vo1=vo*409;
  assign ocv=vo1[34:25];
  
endmodule
